#include <stdio.h>
#include <string.h>

#include "base/base.h"
#include "asm/macroassembler.h"
#include "asm/cpu.h"
#include "asm/dumper.h"
#include "os/os.h"

#include "tests/test-utils.h"

using namespace l8;

static int fn1(int a)
{
    return a + 1000;
}

static inline void test_dasm()
{
    byte * afn = (byte *)&fn1;
    Dumper::Decode(stdout, afn, afn + 32);
}

static inline void test_gen1()
{
    size_t allocated;
    const size_t buf_size = 0x100;
    void * exec_buffer = OS::Allocate(buf_size, &allocated, true);
    ASSERT(allocated >= buf_size);

    Assembler a(exec_buffer, allocated);

#define __ a.

    __ push(rbp);
    __ movq(rbp, rsp);

    __ movl(rax, Immediate(0x101));

    __ leave();
    __ ret(0);
#undef __

    CodeDesc desc;
    a.GetCode(&desc);

    //Dumper::Decode(stdout, desc.buffer, desc.buffer + desc.instr_size);

    CPU::FlushICache(exec_buffer, allocated);

    typedef int64_t (*F0)();
    F0 func = function_cast<F0>(static_cast<Address>(exec_buffer));

    int64_t ret = func();
    fprintf(stdout, "ret = %ld\n\n", ret);

    OS::Free(exec_buffer, allocated);
}

void test()
{
    fprintf(stdout, "in test-linux-x64.\n");

    //test_dasm();
    test_gen1();
}
